﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Windows.Data;

namespace TotalSystems.Core.Controls
{
    public partial class LabeledText : UserControl
    {
        decimal _value;
        bool _isNumericCurrencyEventsHandled;
        bool _isCurrencyCorrection;
        bool _isTextBoxLostFocusEvent;
        #region Constractor
        public LabeledText()
        {
            InitializeComponent();

            if (IsCurrency || IsNumeric)
            {
                
            }
        }

        #endregion

        #region  DependencyProperty
        public static DependencyProperty LableWidthProperty = DependencyProperty.Register("LableWidth",          //Name
        typeof(double),       //Type
        typeof(LabeledText),     //Owner of the Property
        new PropertyMetadata(125d, new PropertyChangedCallback(OnLableWidthPropertyChanged))
        );

        public static DependencyProperty TextProperty = DependencyProperty.Register("Text",          //Name
        typeof(string),       //Type
        typeof(LabeledText),     //Owner of the Property
        new PropertyMetadata((string)null, new PropertyChangedCallback(OnTextPropertyChanged))
        );

        public static DependencyProperty LabelTextProperty = DependencyProperty.Register("LabelText",
            typeof(string),
            typeof(LabeledText),
            new PropertyMetadata("Label", new PropertyChangedCallback(OnLabelTextChanged))
            );

        public static DependencyProperty IsCurrencyProperty = DependencyProperty.Register("IsCurrency",
            typeof(bool),
            typeof(LabeledText),
            new PropertyMetadata(false, new PropertyChangedCallback(OnIsCurrencyNumericChanged))
            );

        public static DependencyProperty IsNumericProperty = DependencyProperty.Register("IsNumeric",
            typeof(bool),
            typeof(LabeledText),
            new PropertyMetadata(false, new PropertyChangedCallback(OnIsCurrencyNumericChanged))
            );

        #endregion

        #region  CallBack
        private static void OnLableWidthPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var lableTextCtrl = sender as LabeledText;
            if (e.NewValue != null)
            {
                //lableTextCtrl.textBox1.Width = (double)e.NewValue;
                //lableTextCtrl.label1.Width = lableTextCtrl.LayoutRoot.Width;// (double)e.NewValue;
                //lableTextCtrl.textBox1.HorizontalAlignment = HorizontalAlignment.Left;
            }
        }

        private static void OnTextPropertyChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            
            var lableTextCtrl = sender as LabeledText;

            if (lableTextCtrl._isTextBoxLostFocusEvent)
            {
                lableTextCtrl._isTextBoxLostFocusEvent = false;
                return;
            }
            
            if (lableTextCtrl.IsCurrency && !string.IsNullOrEmpty((string)e.NewValue))
            {
                lableTextCtrl.textBox1.Text = lableTextCtrl.FormatTextForCurrency((string)e.NewValue);
            }
            else
            {
                lableTextCtrl.textBox1.Text = (string)e.NewValue??string.Empty;
            }
            //var lableTextCtrl = sender as LabeledText;
            //if (e.NewValue != null)
            //    lableTextCtrl.textBox1.Text = (string)e.NewValue;
        }

        private static void OnLabelTextChanged(object sender, DependencyPropertyChangedEventArgs e)
        { }

        private static void OnIsCurrencyNumericChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            var lbldText = sender as LabeledText;
            if ((bool)e.NewValue && !lbldText._isNumericCurrencyEventsHandled)
            {
                lbldText.textBox1.TextChanged += lbldText.textBox1_TextChanged;
                lbldText.textBox1.KeyDown += lbldText.textBox1_KeyDown;
                lbldText.textBox1.KeyUp += lbldText.textBox1_KeyUp;
                lbldText._isNumericCurrencyEventsHandled = true;
            }
            else if (!(bool)e.NewValue && lbldText._isNumericCurrencyEventsHandled)
            {
                lbldText.textBox1.TextChanged -= lbldText.textBox1_TextChanged;
                lbldText.textBox1.KeyDown -= lbldText.textBox1_KeyDown;
                lbldText.textBox1.KeyUp -= lbldText.textBox1_KeyUp;
                lbldText._isNumericCurrencyEventsHandled = false;
            }
        }
        #endregion

        #region  Property
        public double LableWidth
        {
            get { return (double)GetValue(LableWidthProperty); }
            set { SetValue(LableWidthProperty, value); }
        }

        public string LabelText
        {
            get { return (string)GetValue(LabelTextProperty); }
            set { SetValue(LabelTextProperty, value); }
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        private bool _isMandatory;
        public bool IsMandatory
        {
            get { return _isMandatory; }
            set
            {
                _isMandatory = value;
                if (value)
                    lblMandatory.Visibility = System.Windows.Visibility.Visible;
                else
                    lblMandatory.Visibility = System.Windows.Visibility.Collapsed;
            }
        }


        public bool IsCurrency
        {
            get { return (bool)GetValue(IsCurrencyProperty); }
            set
            {
                SetValue(IsCurrencyProperty, value);
            }
        }

        public bool IsNumeric
        {
            get { return (bool)GetValue(IsNumericProperty); }
            set
            {
                SetValue(IsNumericProperty, value);
            }
        }

        #endregion

        private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
        {

            int selectionStart = textBox1.SelectionStart;
            bool changed = false;
            List<char> charList = new List<char>();
            for (int i = 0; i < textBox1.Text.Length; i++)
            {
                if (IsValidChar(textBox1.Text[i], i))
                {
                    charList.Add(textBox1.Text[i]);
                }
                else
                {
                    if (selectionStart >= i)
                    {
                        selectionStart--;
                    }
                    changed = true;
                }
            }
            if (changed)
            {
                string text = new string(charList.ToArray());
                //textBox1.Text = text;
                textBox1.SetValue(TextBox.TextProperty, text);
                textBox1.SelectionStart = selectionStart;
            }
            decimal newValue;
            if (!decimal.TryParse(textBox1.Text.Replace(",",string.Empty), out newValue) && !string.IsNullOrWhiteSpace(textBox1.Text))
            {
                //textBox1.Text = value.ToString();
                textBox1.SetValue(TextBox.TextProperty, _value.ToString());
                textBox1.SelectionStart = textBox1.Text.Length;
            }
            else
            {
                _value = newValue;
            }

        }

        private bool IsValidChar(char c, int index)
        {
            
            bool isValid = ((c == '-' && index == 0) || c == '0' || c == '1' || c == '2' || c == '3' || c == '4' || c == '5' || c == '6' || c == '7' || c == '8' || c == '9');
            if (IsCurrency)
                return isValid || c == ',';
            else
                return isValid;
        }

        private void HandleKeyEvent(KeyEventArgs e)
        {
            e.Handled = true;
            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
            {
                e.Handled = false;
            }
            if (e.Key == Key.Back || e.Key == Key.Delete || e.Key == Key.Left || e.Key == Key.Right ||
                e.Key == Key.D0 || e.Key == Key.D1 || e.Key == Key.D2 || e.Key == Key.D3 || e.Key == Key.D4 || e.Key == Key.D5 || e.Key == Key.D6 ||
                e.Key == Key.D7 || e.Key == Key.D8 || e.Key == Key.D9 ||
                e.Key == Key.NumPad0 || e.Key == Key.NumPad1 || e.Key == Key.NumPad2 || e.Key == Key.NumPad3 || e.Key == Key.NumPad4 || e.Key == Key.NumPad5 || e.Key == Key.NumPad6 ||
                e.Key == Key.NumPad7 || e.Key == Key.NumPad8 || e.Key == Key.NumPad9)
            {
                e.Handled = false;
            }
            else if ((e.Key == Key.Subtract || (e.Key == Key.Unknown && e.PlatformKeyCode == 189)) && textBox1.SelectionStart == 0 && (textBox1.Text.Length == 0 || textBox1.Text[0] != '-'))
            {
                e.Handled = false;
            }
        }

        private void textBox1_KeyDown(object sender, KeyEventArgs e)
        {
            HandleKeyEvent(e);
        }

        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            HandleKeyEvent(e);
        }

        private void textBox1_LostFocus(object sender, RoutedEventArgs e)
        {
            _isTextBoxLostFocusEvent = true;
            Text = textBox1.Text;
            if (IsCurrency)
            {
                //_isCurrencyCorrection = true;
                
               textBox1.Text = FormatTextForCurrency(textBox1.Text);
            }
        }

        private string FormatTextForCurrency(string text)
        {
            int commaIndex = 3;
            text = text.Replace(",", string.Empty);
            while (text.Length > commaIndex)
            {
                text= text.Insert(commaIndex, ",");
                commaIndex += 4;
            }
            return text;
        }

         

    }
}
